package com.utils;

import com.utils.exception.CodeException;

import java.util.Collection;
import java.util.Objects;

/**
 * 响应代码枚举接口，所有响应代码扩展都必须实现该接口，包括调用第三方的响应代码
 *
 * @author 谢长春 2020-07-09
 */
public interface ICode {

    /**
     * 枚举名称
     *
     * @return {@link String}
     */
    String name();

    /**
     * 获取响应消息
     *
     * @return {@link String}
     */
    String getComment();

    /**
     * 使用异常代码构造  CodeException
     *
     * @return {@link CodeException}
     */
    default CodeException toCodeException() {
        return new CodeException(this, this.getComment());
    }

    /**
     * 使用异常代码构造  CodeException
     *
     * @return {@link CodeException}
     */
    default CodeException toCodeException(final Throwable cause) {
        return new CodeException(this, this.getComment(), cause);
    }

    /**
     * 使用异常代码构造 CodeException
     *
     * @param message {@link String} 异常消息
     * @return {@link CodeException}
     */
    default CodeException toCodeException(final String message) {
        return new CodeException(this, message);
    }

    /**
     * 使用异常代码构造 CodeException
     *
     * @param message {@link String} 异常消息
     * @return {@link CodeException}
     */
    default CodeException toCodeException(final String message, final Throwable cause) {
        return new CodeException(this, message, cause);
    }

    /**
     * 格式化异常消息
     *
     * @param exps {@link String} 字符串格式化表达式， String.format("%s:%d", "number", 10)
     * @param args {@link Object} 只支持基本数据类型作为参数，[int,float,double,sttring]
     * @return {@link CodeException}
     */
    default CodeException toCodeException(final String exps, final Object... args) {
        return new CodeException(this, String.format(exps, args));
    }

    /**
     * 格式化异常消息
     *
     * @param exps {@link String} 字符串格式化表达式， String.format("%s:%d", "number", 10)
     * @param args {@link Object} 只支持基本数据类型作为参数，[int,float,double,sttring]
     * @return {@link CodeException}
     */
    default CodeException toCodeException(final Throwable cause, final String exps, final Object... args) {
        return new CodeException(this, String.format(exps, args), cause);
    }

    /**
     * 断言结果为true, 当 value 为 false 时抛出异常
     *
     * @param value {@link Boolean} 断言条件
     */
    default void assertHasTrue(final boolean value) {
        if (!value) {
            throw toCodeException();
        }
    }

    /**
     * 断言结果为true, 当 value 为 false 时抛出异常
     *
     * @param value {@link Boolean} 断言条件
     * @param exps  {@link String} 异常消息， 内部使用 String.format 格式化参数
     * @param args  {@link Object[]} 异常消息参数站位
     */
    default void assertHasTrue(final boolean value, final String exps, final Object... args) {
        if (!value) {
            throw toCodeException(exps, args);
        }
    }

    /**
     * 断言结果为false, 当 value 为 true 时抛出异常
     *
     * @param value {@link Boolean} 断言条件
     */
    default void assertHasFalse(final boolean value) {
        if (value) {
            throw toCodeException();
        }
    }

    /**
     * 断言结果为false, 当 value 为 true 时抛出异常
     *
     * @param value {@link Boolean} 断言条件
     * @param exps  {@link String} 异常消息， 内部使用 String.format 格式化参数
     * @param args  {@link Object[]} 异常消息参数站位
     */
    default void assertHasFalse(final boolean value, final String exps, final Object... args) {
        if (value) {
            throw toCodeException(exps, args);
        }
    }

    /**
     * 断言 value 非空， 当 value 为 null 时抛出异常
     *
     * @param value {@link Object} 断言条件
     */
    default void assertNonNull(final Object value) {
        if (Objects.isNull(value)) {
            throw toCodeException();
        }
    }

    /**
     * 断言 value 非空， 当 value 为 null 时抛出异常
     *
     * @param value {@link Object} 断言条件
     * @param exps  {@link String} 异常消息， 内部使用 String.format 格式化参数
     * @param args  {@link Object[]} 异常消息参数站位
     */
    default void assertNonNull(final Object value, final String exps, final Object... args) {
        if (Objects.isNull(value)) {
            throw toCodeException(exps, args);
        }
    }

    /**
     * 断言 value 非空， 当 value 为 空字符串或 null 时抛出异常
     *
     * @param value {@link String} 断言条件
     */
    default void assertNonBlank(final String value) {
        if (Objects.isNull(value) || value.trim().isEmpty()) {
            throw toCodeException();
        }
    }

    /**
     * 断言 value 非空， 当 value 为 空字符串或 null 时抛出异常
     *
     * @param value {@link String} 断言条件
     * @param exps  {@link String} 异常消息， 内部使用 String.format 格式化参数
     * @param args  {@link Object[]} 异常消息参数站位
     */
    default void assertNonBlank(final String value, final String exps, final Object... args) {
        if (Objects.isNull(value) || value.trim().isEmpty()) {
            throw toCodeException(exps, args);
        }
    }

    /**
     * 断言 value 非空， 当 value 为 空集合或 null 时抛出异常
     *
     * @param value {@link Collection} 断言条件
     */
    default void assertNonEmpty(final Collection<?> value) {
        if (Objects.isNull(value) || value.isEmpty()) {
            throw toCodeException();
        }
    }

    /**
     * 断言 value 非空， 当 value 为 空集合或 null 时抛出异常
     *
     * @param value {@link Collection} 断言条件
     * @param exps  {@link String} 异常消息， 内部使用 String.format 格式化参数
     * @param args  {@link Object[]} 异常消息参数站位
     */
    default void assertNonEmpty(final Collection<?> value, final String exps, final Object... args) {
        if (Objects.isNull(value) || value.isEmpty()) {
            throw toCodeException(exps, args);
        }
    }

    /**
     * 断言 value 非空， 当 value 为 空数组或 null 时抛出异常
     *
     * @param value {@link Object[]} 断言条件
     * @param exps  {@link String} 异常消息， 内部使用 String.format 格式化参数
     * @param args  {@link Object[]} 异常消息参数站位
     */
    default void assertNonEmpty(final Object[] value, final String exps, final Object... args) {
        if (Objects.isNull(value) || value.length == 0) {
            throw toCodeException(exps, args);
        }
    }
}
